package com.han.verifycode.ver.point;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.han.verifycode.CodeConfig;
import com.han.verifycode.data.*;
import com.han.verifycode.data.area.RectangleArea;
import com.han.verifycode.enums.VerifyCodeEnum;
import com.han.verifycode.utils.FileUtil;
import com.han.verifycode.utils.RandomUtil;
import com.han.verifycode.utils.StrUtil;
import com.han.verifycode.ver.PointAreaMatchCode;
import com.han.verifycode.ver.conf.PicturePointConf;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 动态图片识别
 */
public class PicturePointCode implements PointAreaMatchCode {
    private PicturePointConf thisConf;
    private VerifyCodeEnum type = VerifyCodeEnum.PicturePoint;

    @Override
    public RightKey generate(String code, CodeConfig conf) {
        RightKey key = new RightKey(code);
        if (conf == null) {
            thisConf = new PicturePointConf();
        } else {
            thisConf = (PicturePointConf) conf;
        }
        key.setConfig(thisConf);
        key.setType(type);
        key.setWidth(conf.getWidth());
        key.setHeight(conf.getHeight());

        //生成答案
        InputStream dataJson = FileUtil.getFile(thisConf.getDataSource());
        ObjectMapper mapper = StrUtil.getMapper();
        ArrayData<ThingsContent> re = null;
        try {
            re = mapper.readValue(dataJson, new TypeReference<ArrayData<ThingsContent>>() {
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (re == null) {
            return null;
        }
        List<ThingsContent> data = re.getArrays();
        ThingsContent chooseThing = data.get(RandomUtil.getRandom().nextInt(data.size() - 1));
        String name = chooseThing.getName();
        key.setDesc(name);
        key.setTips("请选出图中所有的" + name);

        //随机选图
        int width = thisConf.getWidth();
        int height = thisConf.getHeight();

        int iw = thisConf.getBlockWidth();
        int ih = thisConf.getBlockHeight();
        int nx = width / iw;
        int bx = (width - nx * iw) / (nx + 1);

        int ny = height / ih;
        int by = (height - ny * ih) / (ny + 1);

        int allNum = nx * ny;
        int chooseNum = 0;
        List<String> allRightUrls = chooseThing.getImgs();
        List<String> noRightUrls = new ArrayList<>();
        data.parallelStream().filter(v -> !v.getName().equals(name)).forEach(v -> {
            noRightUrls.addAll(v.getImgs());
        });
        int index = 0;
        List<ImagePosition> ips = new ArrayList<>();
        for (int i = 0; i < nx; i++) {
            for (int j = 0; j < ny; j++) {
                int x = bx + i * (iw + bx);
                int y = by + j * (ih + by);
//                gp2d.drawImage(cimg, x, y, iw, ih, null);
                boolean nb = RandomUtil.getRandom().nextBoolean();
                //超量了
                if (chooseNum >= allNum * 0.8) {
                    nb = false;
                }
                //保证有1个
                if ((i + 1) * (j + 1) == allNum) {
                    nb = true;
                }
                ImagePosition p = new ImagePosition();
                Position leftTop = new Position(x, y);
                p.setP(leftTop);
                p.setHeight(ih);
                p.setWidth(iw);
                p.setIndex(index);
                p.setArea(new RectangleArea(leftTop, iw, ih));
                p.setRight(nb);
                String url;
                if (nb) {
                    url = allRightUrls.get(RandomUtil.getRandom().nextInt(allRightUrls.size() - 1));
                } else {
                    url = noRightUrls.get(RandomUtil.getRandom().nextInt(allRightUrls.size() - 1));
                }
                p.setUrl(url);
                ips.add(p);
                index++;
            }
        }

        //过滤正确答案
        List<Area> listArea = ips.stream().filter(v -> v.isRight()).map(v -> v.getArea()).collect(Collectors.toList());
        key.setPositions(listArea);
        //文件名
        FullPath fullPath = generateFilePath(thisConf.getBasePath(), key.getCode());
        key.setFullPath(fullPath);
        try {
            draw(ips, key);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }

        return key;
    }

    /**
     * 画图
     */
    private void draw(List<ImagePosition> ips, RightKey key) throws IOException {
        //根据总长和 单位长算出border 的长度
        int width = thisConf.getWidth();
        int height = thisConf.getHeight();


        BufferedImage background = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

        Graphics2D gp2d = background.createGraphics();

        for (int i = 0; i < ips.size(); i++) {
            ImagePosition imagePosition = ips.get(i);
            BufferedImage buffImg = ImageIO.read(FileUtil.getFile(imagePosition.getUrl()));
            gp2d.drawImage(buffImg, imagePosition.getP().getX(), imagePosition.getP().getY(), imagePosition.getWidth(), imagePosition.getHeight(), null);
        }
        gp2d.dispose();
        ImageIO.write(background, "jpg", new File(key.getFullPath().getAbsolutePath()));
    }

    @Override
    public CodeConfig getConfig() {
        return thisConf;
    }


}
